/* $RCSFile: ExternalResourceProvider.cs $
 * Apache license v2 2011 by Christian Surieux
 * $Source: ?/ADNCRM.ExternalResourceProvider/ExternalResourceProvider.cs $
 * $log$
 * Revision 19 2011/01/21 17:51:08  christian.surieux
 *   Recover from Sony move files updated in 11/2010 were not in Source Control
 * Revision 6 2010/08/06 19:56:30  christian.surieux
 *   Added Log to All cs files
 */

using System;
using System.Web.Compilation;
using System.Resources;
using System.Reflection;
using System.Globalization;
using System.Threading;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using ADNCRM.CustomResourceProviders;

namespace ADNCRM.CustomResourceProviders.ExternalResourceProvider
{
    /// <summary>
    /// Resource provider for accessing external resources. 
    /// </summary>
    public class GlobalExternalResourceProvider : IResourceProvider
    {
        private string m_classKey;
        private string m_assemblyName;

        private ResourceManager m_resourceManager;

        /// <summary>
        /// Constructs an instance of the provider with the specified
        /// assembly name and resource type. 
        /// </summary>
        /// <param name="classKey">The assembly name and 
        /// resource type in the format [assemblyName]|[resourceType]
        /// </param>
        public GlobalExternalResourceProvider(string classKey)
        {
            if ( ResourceTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine(string.Format(CultureInfo.InvariantCulture, "[V]GlobalExternalResourceProvider Ctor BEG classKey: ({0})", classKey),ResourceTraceSwitch.Sw.Info);

			if (classKey.IndexOf('|') > 0)
			{
				string[] textArray	    =   classKey.Split('|');
				m_assemblyName		    =   textArray[0];
				m_classKey			    =   textArray[1];
			}
			// CS 23/5/7 when no classkey (i.e. category) present, assume that it is the default key with same name as resource assembly
			else if ( !string.IsNullOrEmpty(classKey) )
			{
				m_assemblyName		    =   classKey;
				m_classKey			    =   classKey;
			}
			else  throw new ArgumentException(String.Format(Thread.CurrentThread.CurrentUICulture, Properties.Resources.Provider_InvalidConstructor, classKey));
            if ( ResourceTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine(string.Format(CultureInfo.InvariantCulture, "[V]GlobalExternalResourceProvider Ctor END classKey: {0}, assembly: {1}", m_classKey,m_assemblyName),ResourceTraceSwitch.Sw.Info);
        }

        private Assembly AppResourcesAssembly 
        {
           get 
           {
              Type buildManagerType     =   typeof(BuildManager);
              PropertyInfo property     =   buildManagerType.GetProperty("AppResourcesAssembly", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.GetField);
              return (Assembly)property.GetValue(null, null);
           }
        }  

        /// <summary>
        /// Loads the resource assembly and creates a 
        /// ResourceManager instance to access its resources.
        /// If the assembly is already loaded, Load returns a reference
        /// to that assembly.
        /// </summary>
        private void EnsureResourceManager()
        {
			if ( ResourceTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture, "[V]GlobalExternalResourceProvider EnsureResourceManager m_assemblyName: {0}", m_assemblyName),ResourceTraceSwitch.Sw.Info);
            if ( m_resourceManager == null )
            {
                lock (this)
                {
					string rmName               =   string.Format(CultureInfo.InvariantCulture, "{0}.{1}", m_assemblyName, m_classKey);
					try
					{
						if ( ResourceTraceSwitch.Sw.TraceVerbose )
                            Trace.WriteLine( string.Format(CultureInfo.InvariantCulture, "[V]GlobalExternalResourceProvider EnsureResourceManager m_assemblyName: {0}", m_assemblyName),ResourceTraceSwitch.Sw.Info);
						Assembly asm            =   Assembly.Load(m_assemblyName);
						if ( ResourceTraceSwitch.Sw.TraceVerbose )
                            Trace.WriteLine( string.Format(CultureInfo.InvariantCulture, "[V]GlobalExternalResourceProvider EnsureResourceManager assembly successfully loaded m_assemblyName: {0}", m_assemblyName),ResourceTraceSwitch.Sw.Info);
						ResourceManager rm      =   new ResourceManager(rmName, asm);
						if ( ResourceTraceSwitch.Sw.TraceVerbose )
                            Trace.WriteLine( string.Format(CultureInfo.InvariantCulture, "[V]GlobalExternalResourceProvider EnsureResourceManager ResourceManager created : {0}", rmName),ResourceTraceSwitch.Sw.Info);
						m_resourceManager       =   rm;
					}
					catch (Exception ex)
					{
						if ( ResourceTraceSwitch.Sw.TraceError )
                            Trace.WriteLine(string.Format(CultureInfo.InvariantCulture, "[E]GlobalExternalResourceProvider EnsureResourceManager ResourceManager: {0}, ex: {1}.", rmName,ex),ResourceTraceSwitch.Sw.Info);
                        Assembly asm                =   null;
                        try
                        {
                            string baseName         =   "Resources." + m_classKey;
                            asm                     =   AppResourcesAssembly;
                            if ( asm != null )
                            {
                                if ( ResourceTraceSwitch.Sw.TraceVerbose )
                                    Trace.WriteLine(string.Format(CultureInfo.InvariantCulture,"[V]GlobalExternalResourceProvider EnsureResourceManager trying baseName: {0}, AppResourcesAssembly: {1}.",baseName,asm.FullName),ResourceTraceSwitch.Sw.Info);
                                m_resourceManager   =   new ResourceManager(baseName,asm);
                                if ( m_resourceManager != null )
                                    m_resourceManager.IgnoreCase = true;
                                if ( ResourceTraceSwitch.Sw.TraceVerbose )
                                    Trace.WriteLine(string.Format(CultureInfo.InvariantCulture,"[V]GlobalExternalResourceProvider EnsureResourceManager found: {0}.",(m_resourceManager != null )),ResourceTraceSwitch.Sw.Info);
                            return;
                            }
                        }
                        catch ( Exception ex1 )
                        {
                            if ( ResourceTraceSwitch.Sw.TraceError )
                                Trace.WriteLine(string.Format(CultureInfo.InvariantCulture,"[E]GlobalExternalResourceProvider EnsureResourceManager AppResourcesAssembly: {0}, ex: {1}.",asm.FullName,ex1),ResourceTraceSwitch.Sw.Info);
                            throw ex;
                        }
						throw ex;
					}
                }
                return;
            }
            if ( ResourceTraceSwitch.Sw.TraceVerbose )
            	Trace.WriteLine( string.Format(CultureInfo.InvariantCulture, "[V]GlobalExternalResourceProvider EnsureResourceManager END existing m_resourceManager BaseName: {0}", m_resourceManager.BaseName),ResourceTraceSwitch.Sw.Info);
        }

        #region IResourceProvider Members

        /// <summary>
        /// Retrieves resources using a ResourceManager instance
        /// for the assembly and resource key of this provider 
        /// instance. 
        /// </summary>
        /// <param name="resourceKey">The resource key to find.</param>
        /// <param name="culture">The culture to find.</param>
        /// <returns>The resource value if found.</returns>
        public object GetObject(string resourceKey,CultureInfo culture)
        {
            if ( ResourceTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine(string.Format(CultureInfo.InvariantCulture, "[V]GlobalExternalResourceProvider GetObject BEG resourceKey={0}, culture='{1}'", resourceKey, (culture==null) ? string.Empty:culture.ToString()),ResourceTraceSwitch.Sw.Info);
            EnsureResourceManager();
            if (culture == null)
            {
                culture     =   CultureInfo.CurrentUICulture;
				if ( ResourceTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine(string.Format(CultureInfo.InvariantCulture, "[V]GlobalExternalResourceProvider GetObject culture set ({0}, {1})", resourceKey, culture),ResourceTraceSwitch.Sw.Info);
            }
            object result   =   m_resourceManager.GetObject(resourceKey, culture);
            if ( ResourceTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine(string.Format(CultureInfo.InvariantCulture, "[V]GlobalExternalResourceProvider GetObject END result='{0}'", (result==null) ? string.Empty:result.ToString()),ResourceTraceSwitch.Sw.Info);
            return result;
        }

        /// <summary>
        /// Implicit expressions are not supported by this provider 
        /// therefore a ResourceReader need not be implemented.
        /// Throws a NotSupportedException.
        /// </summary>
        public System.Resources.IResourceReader ResourceReader
        {
            get
            {
                if ( ResourceTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine("GlobalExternalResourceProvider get_ResourceReader Not supported throwing ex",ResourceTraceSwitch.Sw.Info);
                throw new NotSupportedException();
            }
        }

        #endregion
    }
}